home *** CD-ROM | disk | FTP | other *** search
- //
- // IterativeServer.m
- // SchmoozingExamples
- //
- // Created by garrison on Fri Apr 20 2001.
- // Copyright (c) 2001 Standard Orbit Software, LLC. All rights reserved.
- //
- // Permission is granted to use this code for any purpose, at your own risk.
- // No warranties are expressed or implied.
- //
-
- /* An Algorithm for an Iterative Server [Comer93]
- 1) Create a socket and bind it to a well known port number for the server being offered.
- 2) Establish a listener on the socket for incoming connections.
- 3) Accept the next connection request on the socket and obtain a new socket for the connection.
- 4) Repeatedly read the socket for a client request, generate a response, and send the reply back according to the application’s protocol.
- 5) When finished handling a particular client request, close the connection and go back to step 3, accepting the next connection.
- */
-
- #import <Foundation/Foundation.h>
- #import <OmniNetworking/OmniNetworking.h>
- #import "Connection.h"
- #import "IterativeServer.h"
-
- @implementation IterativeServer
-
- - (void) run
- {
- // Implement an iterative connection processing strategy, as defined
- // by Comer's InterNetworking with TCP/IP, Vol III. The server accepts
- // a new connection, processes it, then closes the connection before handling
- // the next one. Requests will queue up on the listening socket up to the
- // the limit defined by the OS. Darwin permits up to 128 unaccepted connection
- // requests (according to the /usr/include/sys/socket.h header).
-
- ONTCPSocket *connectionSocket = nil;
- Connection *someClient = nil;
- unsigned short connectionCount = 0;
-
- // connectionSocket holds a reference to the accepted connection.
-
- // someClient is an instance of our custom connection handling class.
-
- // connectionCount holds a count of connections accepted to
- // provide some feedback in the spartan console UI.
-
-
- // The server starts here.
- NSLog(@"Iterative Server");
-
- do {
- NSAutoreleasePool *loopPool = [[NSAutoreleasePool alloc] init];
- // Create an autorelease pool to contain memory use in the loop.
-
- NS_DURING
- {
- NSLog(@"Listening for the next connection");
-
- connectionSocket = [listeningSocket acceptConnectionOnNewSocket];
- // Step 3. Accept the next incoming connection. Server execution
- // will block until a connection request is received.
-
- connectionCount += 1;
- // Increment the accepted connection count
-
- NSLog(@"Accepted connection %d from host %@", connectionCount,
- [[connectionSocket remoteAddressHost] hostname]);
- // Some console feedback
-
- someClient = [[Connection alloc] initWithConnectedSocket:connectionSocket];
- // Create a connection object with the.
-
- [someClient processConnection];
- // Step 4. Process the connection in a server-specific way.
-
- NSLog(@"Processed connection %d.", connectionCount);
- // Process the connection. This routine must return before the server
- // can accept and process any subsequent connections.
-
- [someClient release];
- // Step 5. Close the connection and go on to the next one.
-
- [loopPool release];
- }
- NS_HANDLER
- {
- NSLog(@"Exception %@ raised during server processing: %@",
- [localException name], localException);
-
- [loopPool release];
-
- break;
- // Close done the server loop if an error occurs.
- }
- NS_ENDHANDLER
-
-
- } while (1);
- // This server loops forever, accepting new connections. As implemented here,
- // the only way the server will stop operating is if an exception is raised
- // during execution. You would want to add some additional means of gracefully
- // bringing a server down (e.g. handling a SIGKILL or SIGHUP signal).
-
- }
-
-
-
-
- - (id) initWithLocalPort:(unsigned short) aPort
- {
- self = [super init];
-
- if ( self )
- {
- NS_DURING {
- listeningSocket = [[ONTCPSocket tcpSocket] retain];
- // Step 1. Create an ONTCPSocket for the server.
-
- [listeningSocket startListeningOnLocalPort:aPort allowingAddressReuse:YES];
- // Step 2. Start socket listening on the server's well known port. Allowing
- // address reuse is helpful while debugging (it prevents a port from getting
- // locked up if your app crashes or you terminate execution in gdb without
- // closing the socket).
-
- NSLog(@"Listening for connections on host %@:%d", [ONHost localHostname], aPort);
- }
- NS_HANDLER {
- // Handle potential exceptions.
- NSLog(@"Server init raised %@ (%@)", [localException name], localException);
- [listeningSocket release];
- return nil;
- }
- NS_ENDHANDLER
- }
-
- return self;
- }
-
-
- - (void) dealloc
- {
- [listeningSocket release];
-
- [super dealloc];
- }
-
-
- @end
-